﻿using System;
using System.Text;
using System.Linq;
using System.Data;
using System.Configuration;
using System.Runtime.Remoting;
using System.Collections.Generic;

using Microsoft.Practices.Unity;

using Cratos.Tools.General;
using Cratos.Tools.DataObject;
using System.Collections.ObjectModel;
using System.Data.Common;

namespace Cratos.Server.Entity
{
	/// <summary>
	/// Cratos Entity Database class
	/// </summary>
	public abstract class CratosEntityDatabase
	{
		#region Class Constant declarations
		#endregion

		#region Class Event declarations
		#endregion

		#region Class Variable declarations
		private ICratosDataAccess dbAccess;
		#endregion

		#region Class Constructors & Destructors
		/// <summary>
		/// Class Constructor
		/// </summary>
		protected CratosEntityDatabase() { }
		#endregion

		#region Class Properties
		/// <summary>
		/// Reader Has Rows indicator
		/// </summary>
		protected bool DBReaderHasRows
		{
			get
			{
				if (this.dbAccess == null) { return (false); }
				else { return (this.dbAccess.ReaderHasRows); }
			}
		}

		/// <summary>
		/// Database Action Attribute
		/// </summary>
		protected DOCratosActionAttribute DBActionAttribute { get; set; }
		#endregion

		#region Class Methods
		#region Single DO Methods
		/// <summary>
		/// Database Setup Command
		/// </summary>
		/// <param name="cratosDO">Cratos Data Object</param>
		/// <returns>A boolean indicating the success of the method</returns>
		protected virtual bool DBSetupSingleCommand(IDOCratos cratosDO)
		{
			// Declare the required variables
			bool returnValue = false;

			// Set the relevant default values
			this.DBActionAttribute = null;

			// Set the relevant Command Options
			this.dbAccess.DBActionType = cratosDO.DBActionType;
			this.dbAccess.DBActionText = "";

			// Process all the Commands
			foreach (DOCratosActionAttribute currentAction in cratosDO.AllDOActions)
			{
				// Look for the relevant Action for the relevant Action Type
				if ((currentAction.CratosAction == cratosDO.DOAction) &&
						(currentAction.CratosActionType == cratosDO.DBActionType))
				{
					this.DBActionAttribute     = currentAction;
					this.dbAccess.DBActionText = currentAction.ActionString;
					returnValue                = true;
					break;
				}
			}

			// Make sure we have an Action to work with
			if (this.DBActionAttribute == null)
			{
				throw new Exception(string.Format("Action Attribute not specified ({0} - {1}", cratosDO.GetType(), cratosDO.DOAction));
			}

			// Return to calling method
			return (returnValue);
		}

		/// <summary>
		/// Database Setup Single Parameters
		/// </summary>
		/// <param name="cratosDO">Cratos Data Object</param>
		protected virtual void DBSetupSingleParameters(IDOCratos cratosDO)
		{
			// Declare the required variables
			DOCratosActionColumnAttribute[] actionAttributes;

			// Process all the Columns
			foreach (DOCratosColumnAttribute currentColumn in cratosDO.AllDOColumns)
			{
				// Make sure we have a Create Attribute on the column
				actionAttributes = (DOCratosActionColumnAttribute[])cratosDO.GetType().GetProperty(currentColumn.Property).GetCustomAttributes(typeof(DOCratosActionColumnAttribute), false);

				// Process all the Attributes
				foreach (DOCratosActionColumnAttribute currentAttribute in actionAttributes)
				{
					// Make sure it is a Retrieve attribute
					if (currentAttribute.CratosAction == cratosDO.DOAction)
					{
						// Add the SP Parameter
						this.DBAddParameter(string.IsNullOrEmpty(currentAttribute.DBParameterName) ? "@" + currentColumn.DBColumnName :
																																												 currentAttribute.DBParameterName,
																currentColumn.DbType,
																DOCratosHelper.GetPropertyValue(cratosDO, currentColumn.Property),
																currentAttribute.IsMandatory, false, false, SqlDbType.Binary);
					}
				}
			}

			// Return to calling method
			return;
		}
		#endregion

		#region Collection DO Methods
		/// <summary>
		/// Database Setup Command
		/// </summary>
		/// <param name="doCollection">Data Object Collection</param>
		/// <returns>A boolean indicating the success of the method</returns>
		protected virtual bool DBSetupCollectionCommand<T>(IDOCratosCollection<T> doCollection) where T : IDOCratos
		{
			// Declare the required variables
			bool returnValue = false;

			// Set the relevant default values
			this.DBActionAttribute = null;

			// Set the relevant Command Options
			this.dbAccess.DBActionType = doCollection.DataObject.DBActionType;
			this.dbAccess.DBActionText = "";

			// Process all the Commands
			foreach (DOCratosActionAttribute currentAction in doCollection.AllDOActions)
			{
				// Look for the relevant Action for the relevant Action Type
				if ((currentAction.CratosCollectionAction == doCollection.CollectionAction) &&
						(currentAction.CratosActionType == doCollection.DataObject.DBActionType))
				{
					// Update the relevant values
					this.DBActionAttribute     = currentAction;
					this.dbAccess.DBActionText = currentAction.ActionString;

					// Set the return value and break
					returnValue = true;
					break;
				}
			}

			// Make sure we have an Action to work with
			if (this.DBActionAttribute == null)
			{
				throw new Exception(string.Format("Action Attribute not specified ({0} - {1}", doCollection.GetType().Name,
																																											 doCollection.CollectionAction));
			}

			// Return to calling method
			return (returnValue);
		}

		/// <summary>
		/// Database Setup Single Parameters
		/// </summary>
		/// <param name="doCollection">Data Object Collection</param>
		protected virtual void DBSetupCollectionParameters<T>(IDOCratosCollection<T> doCollection) where T : IDOCratos
		{
			// Declare the required variables

			// Handle the Cache Retrieve
			if (doCollection.IsCacheRetrieve)
			{
				// Process all the Columns
				foreach (DOCratosCollectionFilterAttribute currentFilter in doCollection.DataObject.AllDOCollectionFilters)
				{
					// Make sure the Filter is for the current Action
					if (string.IsNullOrEmpty(currentFilter.CratosCustomActionName))
					{
						// Add the relevant parameter
						this.DBAddParameter(currentFilter.DBParameterName, currentFilter.DbType, null, false, false, false, SqlDbType.Variant);
					}
				}
			}
			else
			{
				// Process all the Columns
				foreach (DOCratosCollectionFilterAttribute currentFilter in doCollection.DataObject.AllDOCollectionFilters)
				{
					// Make sure the Filter is for the current Action
					if (string.IsNullOrEmpty(currentFilter.CratosCustomActionName))
					{
						if (currentFilter.IsCustomParameter)
						{
							try
							{
								// Add the SP Parameter
								this.DBAddCustomParameter((DbParameter)DOCratosHelper.InvokeMethod(doCollection.DataObject,
																																									 currentFilter.CustomParameterFunction,
																																									 new object[] 
																																										{ 
																																											currentFilter.DBParameterName,
																																											DOCratosHelper.GetPropertyValue(doCollection.DataObject, currentFilter.Property),
																																											currentFilter.IsMandatory 
																																										}));
							}
							catch (Exception ex)
							{
								throw new Exception("Errors in IsCustomParameter SP Parameter " + currentFilter.DBParameterName, ex);
							}
						}
						else
						{
							try
							{
								// Add the SP Parameter
								this.DBAddParameter(currentFilter.DBParameterName, currentFilter.DbType,
																		DOCratosHelper.GetPropertyValue(doCollection.DataObject, currentFilter.Property),
																		currentFilter.IsMandatory, currentFilter.IsIgnoreDefaultNull, false, SqlDbType.Variant);
							}
							catch (Exception ex)
							{
								throw new Exception("Errors in SP Parameter " + currentFilter.DBParameterName, ex);
							}
						}
					}
					else
					{

					}
				}
			}

			// Return to calling method
			return;
		}
		#endregion

		#region Paging Collection DO Methods
		/// <summary>
		/// Database Setup Command
		/// </summary>
		/// <param name="doCollection">Data Object Collection</param>
		/// <returns>A boolean indicating the success of the method</returns>
		protected virtual bool DBSetupCollectionCommand<T>(IDOCratosPagingCollection<T> doCollection) where T : IDOCratos
		{
			// Declare the required variables
			bool returnValue = false;

			// Set the relevant default values
			this.DBActionAttribute = null;

			// Set the relevant Command Options
			this.dbAccess.DBActionType = doCollection.DataObject.DBActionType;
			this.dbAccess.DBActionText = "";

			// Process all the Commands
			foreach (DOCratosActionAttribute currentAction in doCollection.AllDOActions)
			{
				// Look for the relevant Action for the relevant Action Type
				if ((currentAction.CratosCollectionAction == doCollection.CollectionAction) &&
						(currentAction.CratosActionType == doCollection.DataObject.DBActionType))
				{
					this.DBActionAttribute = currentAction;
					this.dbAccess.DBActionText = currentAction.ActionString;
					returnValue = true;
					break;
				}
			}

			// Make sure we have an Action to work with
			if (this.DBActionAttribute == null)
			{
				throw new Exception(string.Format("Action Attribute not specified ({0} - {1}", doCollection.GetType().Name,
																																											 doCollection.CollectionAction));
			}

			// Return to calling method
			return (returnValue);
		}

		/// <summary>
		/// Database Setup Single Parameters
		/// </summary>
		/// <param name="doCollection">Data Object Collection</param>
		protected virtual void DBSetupCollectionParameters<T>(IDOCratosPagingCollection<T> doCollection) where T : IDOCratos
		{
			// Declare the required variables

			// Handle the Cache Retrieve
			if (doCollection.IsCacheRetrieve)
			{
				// Process all the Columns
				foreach (DOCratosCollectionFilterAttribute currentFilter in doCollection.DataObject.AllDOCollectionFilters)
				{
					// Make sure the Filter is for the current Action
					if (string.IsNullOrEmpty(currentFilter.CratosCustomActionName))
					{
						// Add the relevant parameter
						this.DBAddParameter(currentFilter.DBParameterName, currentFilter.DbType, null, false, false, false, SqlDbType.Variant);
					}
				}
			}
			else
			{
				// Process all the Columns
				foreach (DOCratosCollectionFilterAttribute currentFilter in doCollection.DataObject.AllDOCollectionFilters)
				{
					// Make sure the Filter is for the current Action
					if (string.IsNullOrEmpty(currentFilter.CratosCustomActionName))
					{
						if (currentFilter.IsCustomParameter)
						{
							try
							{
								// Add the SP Parameter
								this.DBAddCustomParameter((DbParameter)DOCratosHelper.InvokeMethod(doCollection.DataObject,
																																									 currentFilter.CustomParameterFunction,
																																									 new object[] 
																																										{ 
																																											currentFilter.DBParameterName,
																																											DOCratosHelper.GetPropertyValue(doCollection.DataObject, currentFilter.Property),
																																											currentFilter.IsMandatory 
																																										}));
							}
							catch (Exception ex)
							{
								throw new Exception("Errors in IsCustomParameter SP Parameter " + currentFilter.DBParameterName, ex);
							}
						}
						else
						{
							try
							{
								// Add the SP Parameter
								this.DBAddParameter(currentFilter.DBParameterName, currentFilter.DbType,
																		DOCratosHelper.GetPropertyValue(doCollection.DataObject, currentFilter.Property),
																		currentFilter.IsMandatory, currentFilter.IsIgnoreDefaultNull, false, SqlDbType.Variant);
							}
							catch (Exception ex)
							{
								throw new Exception("Errors in SP Parameter " + currentFilter.DBParameterName, ex);
							}
						}
					}
					else
					{

					}
				}
			}

			// Return to calling method
			return;
		}
		#endregion

		#region Database Methods
		/// <summary>
		/// Setup the DB Connection
		/// </summary>
		/// <param name="ignoreUnity">Ignore Unity indicator</param>
		/// <param name="dbConnectionName">Database Connection Name</param>
		/// <param name="actionType">Cratos DO Action Type</param>
		/// <returns>A boolean indicating the success of the method</returns>
		protected virtual bool DBConnect(bool ignoreUnity, string dbConnectionName, DOCratosActionType actionType)
		{
			// Declare the required variables
			bool					returnValue = false;
			ObjectHandle	tempObject;

			// Make sure the DB Connection Name is valid
			if (ConfigurationManager.ConnectionStrings[dbConnectionName] == null)
			{
				// Throw an exception
				throw new Exception("Connection Name not specified");
			}
			else
			{
				// Make sure we don't have a connection already
				if ((this.dbAccess == null) || (this.dbAccess.Connection.State != ConnectionState.Open))
				{
					// Handle the Unity indicator
					if (ignoreUnity)
					{
						switch (actionType)
						{
							case DOCratosActionType.StoredProcedure:
								// Create the relevant type
								tempObject     = Activator.CreateInstance("Cratos.Tools.DataAccess", "Cratos.Tools.DataAccess.CratosDBStoredProcedure");
								this.dbAccess = ((ICratosDataAccess)tempObject.Unwrap());
								break;

							case DOCratosActionType.SqlString:
								// Create the relevant type
								tempObject    = Activator.CreateInstance("Cratos.Tools.DataAccess", "Cratos.Tools.DataAccess.CratosDBSqlString");
								this.dbAccess = ((ICratosDataAccess)tempObject.Unwrap());
								break;

							default:
								throw new Exception("Invalid Database Command Type specified");
						}
					}
					else
					{
						switch (actionType)
						{
							case DOCratosActionType.StoredProcedure:
								// Create the relevant type
								this.dbAccess = DOCratosGlobal.UnityContainer.Resolve<ICratosDataAccess>(ConfigurationManager.AppSettings["CratosDataAccessStoredProc"]);
								break;

							case DOCratosActionType.SqlString:
								// Create the relevant type
								this.dbAccess = DOCratosGlobal.UnityContainer.Resolve<ICratosDataAccess>(ConfigurationManager.AppSettings["CratosDataAccessSqlString"]);
								break;

							case DOCratosActionType.CustomADODriver:
								// Create the relevant type
								this.dbAccess = DOCratosGlobal.UnityContainer.Resolve<ICratosDataAccess>(ConfigurationManager.AppSettings["CratosDataAccessCustom"]);
								break;

							default:
								throw new Exception("Invalid Database Command Type specified");
						}
					}

					// Make sure we have a Data Access object
					if (this.dbAccess != null)
					{
						// Setup the connection
						this.dbAccess.ConnectionString = ConfigurationManager.ConnectionStrings[dbConnectionName].ToString();

						// Connect to the database
						this.dbAccess.Connect();

						// Update the relevant settings
						this.dbAccess.CommandTimeout = 600000;
						this.dbAccess.ClearParameters();

						// Set the successful return value
						returnValue = true;
					}
					else { throw new Exception("Failed to create the required Cratos Data Access object"); }
				}
				else { returnValue = true; }
			}

			// return to calling method
			return (returnValue);
		}

		/// <summary>
		/// Database Disconnect
		/// </summary>
		protected virtual void DBDisconnect()
		{
			// Declare the required variables

			// Make sure the DB Access has been created and disconnect it
			if (this.dbAccess != null) { this.dbAccess.Disconnect(); }

			// Return to calling method
			return;
		}

		/// <summary>
		/// Add Parameter to DB Command
		/// </summary>
		/// <param name="parameterName">Parameter Name</param>
		/// <param name="dataType">Data Type</param>
		/// <param name="parameterValue">Parameter Value</param>
		/// <param name="isMandatory">Mandatory indicator</param>
		/// <param name="isIgnoreDefaultNull">Ignore default if null</param>
		/// <param name="useSqlDbType">Use SQL DB Type</param>
		/// <param name="sqlDbType">SQL Data type</param>
		protected void DBAddParameter(string parameterName, DbType dataType, object parameterValue,
																	bool isMandatory, bool isIgnoreDefaultNull, bool useSqlDbType, SqlDbType sqlDbType)
		{
			// Declare the required variables
			bool isValidParameter = true;

			// Handle the data type
			switch (dataType)
			{
				case DbType.Byte:
					// Validate the Mandatory indicator
					if (isMandatory && !isIgnoreDefaultNull && (Convert.ToInt16(parameterValue) == 0)) { isValidParameter = false; }
					else if (!isMandatory && !isIgnoreDefaultNull && !isIgnoreDefaultNull && (Convert.ToInt16(parameterValue) == 0))
					{
						// Add the null parameter to the Command
						this.dbAccess.AddSqlParameter(parameterName, SqlDbType.TinyInt, null, ParameterDirection.Input);
					}
					else
					{
						// Add the parameter to the Command
						this.dbAccess.AddSqlParameter(parameterName, SqlDbType.TinyInt, parameterValue, ParameterDirection.Input);
					}

					break;

				case DbType.Int16:
				case DbType.Int32:
				case DbType.Int64:
					// Validate the Mandatory indicator
					if (isMandatory && !isIgnoreDefaultNull && (Convert.ToInt64(parameterValue) == 0)) { isValidParameter = false; }
					else if (!isMandatory && !isIgnoreDefaultNull && (Convert.ToInt64(parameterValue) == 0))
					{
						// Add the null parameter to the Command
						this.dbAccess.AddParameter(parameterName, dataType, null);
					}
					else
					{
						// Add the parameter to the Command
						this.dbAccess.AddParameter(parameterName, dataType, parameterValue);
					}

					break;

				case DbType.DateTime:
					// Validate the Mandatory indicator
					if (isMandatory && !isIgnoreDefaultNull && (Convert.ToDateTime(parameterValue).Year <= 1753)) { isValidParameter = false; }
					else if (!isMandatory && !isIgnoreDefaultNull && (Convert.ToDateTime(parameterValue).Year <= 1753))
					{
						// Add the null parameter to the Command
						this.dbAccess.AddParameter(parameterName, dataType, null);
					}
					else
					{
						// Add the parameter to the Command
						this.dbAccess.AddParameter(parameterName, dataType, parameterValue);
					}

					break;

				case DbType.Decimal:
					// Validate the Mandatory indicator
					if (isMandatory && !isIgnoreDefaultNull && (Convert.ToDecimal(parameterValue) == Decimal.Zero)) { isValidParameter = false; }
					else if (!isMandatory && !isIgnoreDefaultNull && (Convert.ToDecimal(parameterValue) == Decimal.Zero))
					{
						// Add the null parameter to the Command
						this.dbAccess.AddParameter(parameterName, dataType, null);
					}
					else
					{
						// Handle the SQL Data Type if required
						if (useSqlDbType) { this.dbAccess.AddSqlParameter(parameterName, sqlDbType, parameterValue, ParameterDirection.Input); }
						else { this.dbAccess.AddParameter(parameterName, dataType, parameterValue); }
					}

					break;

				case DbType.String:
					// Validate the Mandatory indicator
					if (isMandatory && !isIgnoreDefaultNull && string.IsNullOrEmpty((string)parameterValue)) { isValidParameter = false; }
					else if (!isMandatory && !isIgnoreDefaultNull && string.IsNullOrEmpty((string)parameterValue))
					{
						// Add the null parameter to the Command
						this.dbAccess.AddParameter(parameterName, dataType, null);
					}
					else
					{
						// Add the parameter to the Command
						this.dbAccess.AddParameter(parameterName, dataType, parameterValue);
					}

					break;

				case DbType.Guid:
					// Validate the Mandatory indicator
					if (isMandatory && !isIgnoreDefaultNull && ((Guid)parameterValue == Guid.Empty)) { isValidParameter = false; }
					else if (!isMandatory && !isIgnoreDefaultNull && ((Guid)parameterValue == Guid.Empty))
					{
						// Add the null parameter to the Command
						this.dbAccess.AddParameter(parameterName, dataType, null);
					}
					else
					{
						// Add the parameter to the Command
						this.dbAccess.AddParameter(parameterName, dataType, parameterValue);
					}

					break;

				default:
					// Validate the Mandatory indicator
					if (isMandatory && (parameterValue == null)) { isValidParameter = false; }
					else
					{
						// Add the parameter to the Command
						this.dbAccess.AddParameter(parameterName, dataType, parameterValue);
					}

					break;
			}

			// Valid parameter
			if (!isValidParameter)
			{
				// Add an error to the error list
				throw new Exception(string.Format("DB Parameter [{0}] is mandatory but no value was supplied", parameterName));
			}

			// Return to calling method
			return;
		}

		/// <summary>
		/// Add Custom Parameter
		/// </summary>
		/// <param name="dbParameter">Custom Parameter</param>
		protected void DBAddCustomParameter(DbParameter dbParameter)
		{
			// Declare the required variables

			// Add the parameter to the Command
			this.dbAccess.Command.Parameters.Add(dbParameter);

			// Return to calling method
			return;
		}

		/// <summary>
		/// Database Execute Reader
		/// </summary>
		/// <returns>A boolean indicating the success of the method</returns>
		protected bool DBExecuteReader()
		{
			// Declare the required variables

			// Execute the Action
			this.dbAccess.ExecuteReader();

			// Handle any errors
			return (this.dbAccess.Result == CratosDatabaseResult.Success);
		}

		/// <summary>
		/// Database Execute Non-Query
		/// </summary>
		/// <returns>A boolean indicating the success of the method</returns>
		protected bool DBExecuteNonQuery()
		{
			// Declare the required variables

			// Execute the Action
			this.dbAccess.ExecuteNonQuery();

			// Handle any errors
			return (true);
		}

		/// <summary>
		/// Database Reader Read
		/// </summary>
		/// <returns></returns>
		protected bool DBReaderRead()
		{
			// Execute the Reader Read
			return(this.dbAccess.ReaderRead());
		}
		#endregion

		#region Data Loading methods
		/// <summary>
		/// Load Data from the Data Reader
		/// </summary>
		protected void DBLoadDataFromReader(IDOCratos cratosDO)
		{
			// Declare the required variables

			// Process all the Data Object columns
			foreach (DOCratosColumnAttribute currentColumn in cratosDO.AllDOColumns)
			{
				// Make sure we are allowed to load the column
				if (!currentColumn.IgnoreReturnValue)
				{
					// Make sure the column exists in the data row
					if (this.dbAccess.ReaderContainsField(currentColumn.DBColumnName))
					{
						// Make sure the field contains a value
						if (this.dbAccess.ReaderIsFieldNull(currentColumn.DBColumnName))
						{
							// Set the property to its default value
							this.DBSetDOPropertyNull(cratosDO, currentColumn.Property, currentColumn.DbType);
						}
						else
						{
							// Set the property value
							this.DBSetDOPropertyValue(cratosDO, currentColumn.Property, currentColumn.DbType,
																				this.dbAccess.ReaderGetValue(currentColumn.DBColumnName, currentColumn.DbType));
						}
					}
				}
			}

			// Set the loaded indicator
			cratosDO.IsLoaded = true;

			// Return to calling method
			return;
		}

		/// <summary>
		/// Set Data Object Property to Null
		/// </summary>
		/// <param name="doCratos">Cratos Data Object</param>
		/// <param name="propertyName"></param>
		/// <param name="dbType"></param>
		private void DBSetDOPropertyNull(IDOCratos doCratos, string propertyName, DbType dbType)
		{
			// Declare the required variables

			// Handle the relevant Data Type
			switch (dbType)
			{
				case DbType.Decimal:
					// Set the default null value
					doCratos.GetType().GetProperty(propertyName).SetValue(doCratos, 0.0m, null);
					break;

				case DbType.Boolean:
					// Set the default null value
					doCratos.GetType().GetProperty(propertyName).SetValue(doCratos, false, null);
					break;

				case DbType.DateTime:
					// Set the default null value
					doCratos.GetType().GetProperty(propertyName).SetValue(doCratos, new DateTime(1753, 1, 1), null);
					break;

				case DbType.String:
					// Set the default null value
					doCratos.GetType().GetProperty(propertyName).SetValue(doCratos, string.Empty, null);
					break;

				default:
					// Set the default null value
					doCratos.GetType().GetProperty(propertyName).SetValue(doCratos, null, null);
					break;
			}

			// Return to calling method
			return;
		}

		/// <summary>
		/// Set Data Object Property Value
		/// </summary><param name="doCratos">Cratos Data Object</param>
		/// <param name="propertyName"></param>
		/// <param name="dbType"></param>
		/// <param name="newValue"></param>
		protected void DBSetDOPropertyValue(IDOCratos doCratos, string propertyName, DbType dbType, object newValue)
		{
			// Declare the required variables

			try
			{
				// Handle the relevant Data Type
				switch (dbType)
				{
					case DbType.Int16:
						doCratos.GetType().GetProperty(propertyName).SetValue(doCratos, Convert.ToInt16(newValue), null);
						break;

					case DbType.Int32:
						doCratos.GetType().GetProperty(propertyName).SetValue(doCratos, Convert.ToInt32(newValue), null);
						break;

					case DbType.Int64:
						doCratos.GetType().GetProperty(propertyName).SetValue(doCratos, Convert.ToInt64(newValue), null);
						break;

					case DbType.Decimal:
						doCratos.GetType().GetProperty(propertyName).SetValue(doCratos, Convert.ToDecimal(newValue), null);
						break;

					case DbType.DateTime:
						doCratos.GetType().GetProperty(propertyName).SetValue(doCratos, Convert.ToDateTime(newValue), null);
						break;

					case DbType.Boolean:
						doCratos.GetType().GetProperty(propertyName).SetValue(doCratos, Convert.ToBoolean(newValue), null);
						break;

					case DbType.String:
						doCratos.GetType().GetProperty(propertyName).SetValue(doCratos, Convert.ToString(newValue), null);
						break;

					case DbType.Guid:
						doCratos.GetType().GetProperty(propertyName).SetValue(doCratos, new Guid(Convert.ToString(newValue)), null);
						break;

					default:
						doCratos.GetType().GetProperty(propertyName).SetValue(doCratos, newValue, null);
						break;
				}
			}
			catch (Exception runtimeException)
			{
				// Throw a new exception
				throw new Exception(string.Format("Runtime error occurred when setting {0}.{1}\n{2}", doCratos.GetType(), 
																																															propertyName, runtimeException.ToString()));
			}

			// Return to calling method
			return;
		}
		#endregion
		#endregion

		#region Class Support Methods
		#endregion
	}
}
